/*
 * JVM_StackFrame.h
 *
 *  Created on: 03.01.2011
 *      Author: Tavin
 */

#include <stdint.h>

#include "JVM_Handle.h"
#include "JVM_DataTypes.h"
#include "JVM_Method.h"
#include "JVM_CP_Table.h"

#include "JVM_DataTypes.h"

#ifndef JVM_STACKFRAME_H_
#define JVM_STACKFRAME_H_


typedef struct
{
	void * previus;

	JVM_Method_t *currentMethod;
	JVM_CP_Table_t *currentCpTable;

	uint16_t  variablePointer;
	uint16_t  stackPointer;
	uint16_t  typePointer;
	uint16_t  PC;


	uint32_t  stackData[];

} JVM_StackFrame_t;






/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_pushIntValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_pushIntValue(JVM_StackFrame_t *myStackFrame,int32_t value)
{
		myStackFrame->stackData[myStackFrame->stackPointer++]=value;
}



/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_pushLongValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_pushLongValue(JVM_StackFrame_t *myStackFrame,int64_t value)
{

		myStackFrame->stackData[myStackFrame->stackPointer++]=value>>32;
		myStackFrame->stackData[myStackFrame->stackPointer++]=value&0xffffffff;
}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_pushFloatValue				Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_pushFloatValue(JVM_StackFrame_t *myStackFrame,float value)
{
	union data_value_32 myData;
	myData.floatValue=value;

		myStackFrame->stackData[myStackFrame->stackPointer++]=myData.intValue;
}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_pushLongValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_pushDoubleValue(JVM_StackFrame_t *myStackFrame,double value)
{
	union data_value_64 myData;

	myData.doubleValue=value;
		myStackFrame->stackData[myStackFrame->stackPointer++]=myData.longValue>>32;
		myStackFrame->stackData[myStackFrame->stackPointer++]=myData.longValue&=0xffffffff;
}



/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_pushIntValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_pushReference(JVM_StackFrame_t *myStackFrame,JVM_HandleNumber_t reference)
{
	//TODO mark Variable as Reference!!!!
		myStackFrame->stackData[myStackFrame->stackPointer++]=reference;
}



/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_popIntValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

int32_t static inline JVM_StackFrame_popIntValue(JVM_StackFrame_t *myStackFrame)
{
	return(myStackFrame->stackData[--myStackFrame->stackPointer]);
}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_popIntValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

JVM_HandleNumber_t static inline JVM_StackFrame_popReference(JVM_StackFrame_t *myStackFrame)
{
	return(myStackFrame->stackData[--myStackFrame->stackPointer]);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_popLongValue					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

int64_t static inline JVM_StackFrame_popLongValue(JVM_StackFrame_t *myStackFrame)
{


	uint64_t value;

	value=myStackFrame->stackData[--myStackFrame->stackPointer];
	value+=((uint64_t)myStackFrame->stackData[--myStackFrame->stackPointer]<<32);

	return(value);
}



/****************************************************************************************/
/*																						*/
/*	Function : JVM_Opcode_popFloatValue						Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

float static inline JVM_StackFrame_popFloatValue(JVM_StackFrame_t *myStackFrame)
{
	union data_value_32 myData;

	myData.intValue=myStackFrame->stackData[--myStackFrame->stackPointer];
	return(myData.floatValue);
}



/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_popDoubleValue				Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

double static inline JVM_StackFrame_popDoubleValue(JVM_StackFrame_t *myStackFrame)
{

	union data_value_64 myData;


	myData.longValue=myStackFrame->stackData[--myStackFrame->stackPointer];
	myData.longValue+=((uint64_t)myStackFrame->stackData[--myStackFrame->stackPointer]<<32);

	return(myData.doubleValue);
}





/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_setIntVar						Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_setIntVar(JVM_StackFrame_t *myStackFrame,uint16_t index,int32_t value)
{

	myStackFrame->stackData[myStackFrame->variablePointer+index]=value;

}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_setReferenceVar				Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_setReferenceVar(JVM_StackFrame_t *myStackFrame,uint16_t index,JVM_HandleNumber_t reference)
{

	myStackFrame->stackData[myStackFrame->variablePointer+index]=reference;

}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_setLongVar					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

void static inline JVM_StackFrame_setLongVar(JVM_StackFrame_t *myStackFrame,uint16_t index,int64_t value)
{

	myStackFrame->stackData[myStackFrame->variablePointer+index++]=value>>32;
	myStackFrame->stackData[myStackFrame->variablePointer+index]=value&0xffffffff;


}




/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_getIntVar						Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

int32_t static inline JVM_StackFrame_getIntVar(JVM_StackFrame_t *myStackFrame,uint16_t index)
{
	return(myStackFrame->stackData[myStackFrame->variablePointer+index]);
}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_getReferenceVar					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

JVM_HandleNumber_t static inline JVM_StackFrame_getReferenceVar(JVM_StackFrame_t *myStackFrame,uint16_t index)
{
	return(myStackFrame->stackData[myStackFrame->variablePointer+index]);
}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_getFloatVar					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

float static inline JVM_StackFrame_getFloatVar(JVM_StackFrame_t *myStackFrame,uint16_t index)
{
	union data_value_32 myData;

	myData.intValue=myStackFrame->stackData[myStackFrame->variablePointer+index];

	return(myData.floatValue);

}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_getLongVar					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

int64_t static inline JVM_StackFrame_getLongVar(JVM_StackFrame_t *myStackFrame,uint16_t index)
{
	uint64_t value;

	value=((uint64_t)myStackFrame->stackData[myStackFrame->variablePointer+index++]<<32);
	value+=myStackFrame->stackData[myStackFrame->variablePointer+index];

	return(value);

}


/****************************************************************************************/
/*																						*/
/*	Function : JVM_StackFrame_getDoubleVar					Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.4			Status : Working   			*/
/*																						*/
/****************************************************************************************/

double static inline JVM_StackFrame_getDoubleVar(JVM_StackFrame_t *myStackFrame,uint16_t index)
{
	union data_value_64 myData;

	myData.longValue=((uint64_t)myStackFrame->stackData[myStackFrame->variablePointer+index++]<<32);
	myData.longValue+=myStackFrame->stackData[myStackFrame->variablePointer+index];

	return(myData.doubleValue);

}

#endif /* JVM_STACKFRAME_H_ */




JVM_StackFrame_t * JVM_StackFrame_new(JVM_CP_Table_t *myTable, JVM_Method_t *myMethod);
uint16_t JVM_StackFrame_destroy(JVM_StackFrame_t *myStackFrame );

// author: D.R. destroy complete stack
uint16_t JVM_Stack_unroll(JVM_StackFrame_t *myStackFrame);
